from typing import List, Type

from emi.bar.data import DailyBar, Interval
from emi.bar.storage.model import BaseDBModel
from emi.core.DBSource import DBSource, PeeweeModelSource
import peewee
from datetime import datetime,date

class DailyBarModel(BaseDBModel):

    symbol: int = peewee.TextField()
    datetime:date = peewee.DateField()
    interval: int = peewee.SmallIntegerField()

    _int1: int = peewee.IntegerField(default=-1)
    _int2: int = peewee.IntegerField(default=-1)
    _int3: int = peewee.IntegerField(default=-1)

    _float1: int = peewee.FloatField(default=None,null=True)
    _float2: int = peewee.FloatField(default=None,null=True)
    _float3: int = peewee.FloatField(default=None,null=True)

    _str1: str = peewee.TextField(default=None,null=True)
    _str2: str = peewee.TextField(default=None,null=True)
    _str3: str = peewee.TextField(default=None,null=True)

    core_data: bytes = peewee.BlobField(null=True)



    @staticmethod
    def from_data(bar: DailyBar):

        db_bar = DailyBarModel()
        db_bar.symbol = bar.symbol
        db_bar.interval = bar.interval.value
        db_bar.datetime = bar.datetime.date()

        db_bar._int1 = bar._int1
        db_bar._int2 = bar._int2
        db_bar._int3 = bar._int3

        db_bar._float1 = bar._float1
        db_bar._float2 = bar._float2
        db_bar._float3 = bar._float3

        db_bar._str1 = bar._str1
        db_bar._str2 = bar._str2
        db_bar._str3 = bar._str3
        db_bar.core_data = bar.get_blob()

        return db_bar

    def to_bar(self, class_type: Type[DailyBar]):
        interval = Interval(self.interval)
        time = datetime(year=self.datetime.year,month=self.datetime.month,day=self.datetime.day)
        bar: DailyBar = class_type(interval=interval, datetime=time, symbol=self.symbol)

        bar._int1 = self._int1
        bar._int2 = self._int2
        bar._int3 = self._int3

        bar._float1 = self._float1
        bar._float2 = self._float2
        bar._float3 = self._float3

        bar._str1 = self._str1
        bar._str2 = self._str2
        bar._str3 = self._str3
        bar.set_blob(self.core_data,form_storage=True)

        return bar


class DailyBarStorage:

    def __init__(self,source:DBSource,indexes_desc = None,table_name = None):
        if indexes_desc is None:
            indexes_desc = (
                    (("symbol", "datetime","interval"), True),
                )
        if table_name is None:
            table_name = 'daily_bar_default'
        self.source = source.init_peewee(table_name,DailyBarModel,indexes=indexes_desc,ignore_inited=True)


    def get_db_source(self)->PeeweeModelSource[DailyBarModel]:
        return self.source

    def get_day_list(self,interval:Interval = None)->List[date]:
        with self.source.use_peewee() as db_model:
            if interval is None:
                s = (db_model.select(db_model.datetime)
                     .order_by(db_model.datetime.asc()).distinct())
                return [ model.datetime  for model in s]
            else:
                s = (db_model.select(db_model.datetime)
                     .where(db_model.interval == interval.value)
                     .order_by(db_model.datetime.asc()).distinct())
                return [model.datetime for model in s]

    def get_symbol_list(self) -> List[str]:
        """
        返回所有的symbol列表
        """
        with self.source.use_peewee() as db_model:
            s = (db_model.select(db_model.symbol).distinct())
            return [v.symbol for v in s]

    def save_bars(self,bars:List[DailyBar]):
        """
        保存Bar数据。
        """
        ds = [DailyBarModel.from_data(i) for i in bars]
        with self.source.use_peewee() as db_model:
            db_model.save_all(ds)

    def size(self, symbol: str = None) -> int:
        with self.source.use_peewee() as db_model:
            if symbol is None:
                return db_model.select().count()
            else:
                return db_model.select().where(db_model.symbol == symbol).count()

    def clear(self, symbol: str = None,interval:Interval = None,time:datetime = None):
        with self.source.use_peewee() as db_model:
            if symbol is not None or interval is not None:
                condition = []
                if symbol is not None:
                    condition.append(db_model.symbol == symbol)
                if interval is not None:
                    condition.append(db_model.interval == interval.value)
                if time is not None:
                    condition.append(db_model.datetime == time.date())

                db_model.delete().where(*condition).execute()
            else:
                ##情况表
                db_model.drop_table()
                db_model.create_table()

    def clear_before(self, time: datetime):
        with self.source.use_peewee() as db_model:
            db_model.delete().where(
                (db_model.datetime <= time)
            ).execute()